﻿using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Groups;
using InkjetControl.codec;
using InkjetControl.events;
using InkjetControl.NLog;
using InkjetControl.services.resolvers;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace InkjetControl.services.handler
{
    public class ServerMessageHandler : SimpleChannelInboundHandler<Message>
    {

        private static readonly MessageResolverFactory resolverFactory = MessageResolverFactory.GetInstance();
        private static IChannelGroup clientsGroup;
        private static readonly ConcurrentDictionary<string, IChannel> clientIdByIp = new ConcurrentDictionary<string, IChannel>();

        public ServerMessageHandler()
        {
            Log.Logger.Info("ServerMessageHandler");
        }

        private void EventBus_OnSendMsgHandler(string machineCode, Message msg)
        {
            Log.Logger.Info("EventBus_OnSendMsgHandler machineCode:{0}, msg:{1}", machineCode, msg);
            if (clientIdByIp.TryGetValue(machineCode, out IChannel channel))
            {
                _ = channel.WriteAndFlushAsync(msg);
            }
        }

        protected override void ChannelRead0(IChannelHandlerContext ctx, Message msg)
        {
            // 获取消息处理器
            IResolver resolver = resolverFactory.GetMessageResolver(msg, true);
            // Log.Logger.Debug("Srv ChannelRead0 : [ sessionID:{0}], recv body:{1}", msg.SessionId, msg.Body);
            // 对消息进行处理并获取响应数据
            Message resulte = resolver.Resolve( msg);
            if (resulte.MessageType == MessageType.RESPONSE && resulte.Body?.Cmd == NetCmd.LOGIN)
            {
                if (!clientIdByIp.ContainsKey(msg.MachineCode))
                {
                    _ = clientIdByIp.TryAdd(msg.MachineCode, ctx.Channel);
                    EventBus.OnSendMsgHandler += EventBus_OnSendMsgHandler;
                    EventBus.OnLogin(msg.MachineCode, msg.MachineLabel, ctx.Channel);
                }
            }
            ctx.WriteAndFlushAsync(resulte);
        }

        private void Event_LoginChange(object sender, ClientLoginEventArgs e)
        {
            throw new NotImplementedException();
        }

        public override void ChannelReadComplete(IChannelHandlerContext context)
        {
            base.ChannelReadComplete(context);
            context.Flush();
        }

        public override void ChannelActive(IChannelHandlerContext context)
        {
            base.ChannelActive(context);
            IChannelGroup g = clientsGroup;
            if (g == null)
            {
                lock (this)
                {
                    if (clientsGroup == null)
                    {
                        g = clientsGroup = new DefaultChannelGroup(context.Executor);
                    }
                }
            }
            g.Add(context.Channel);

            Message msg = new Message()
            {
                MessageType = MessageType.REQUEST,
            };
            string info = string.Format("Welcome {0} to Inkject Control server!", ((IPEndPoint)context.Channel.RemoteAddress).Address);
            msg.Body = Message.GenerateMsgBody(NetCmd.CONNECTION, ref info);
            context.WriteAndFlushAsync(msg);
        }
        public override void ChannelInactive(IChannelHandlerContext context)
        {
            base.ChannelInactive(context);
            Log.Logger.Error("ChannelInactive ");
        }
        public override void ChannelRegistered(IChannelHandlerContext context)
        {
            base.ChannelRegistered(context);
            resolverFactory.RegisterResolver(new RequestMessageResolver(), true);   // 注册request消息处理器
            resolverFactory.RegisterResolver(new ResponseMessageResolver(), true);// 注册response消息处理器
            resolverFactory.RegisterResolver(new PingMessageResolver(), true);  // 注册ping消息处理器
            resolverFactory.RegisterResolver(new PongMessageResolver(), true);	// 注册pong消息处理器

        }
        public override void HandlerAdded(IChannelHandlerContext context)
        {
            base.HandlerAdded(context);
        }
        public override void HandlerRemoved(IChannelHandlerContext context)
        {
            Log.Logger.Error("HandlerRemoved ");
            base.HandlerRemoved(context);
            RemoveChannel(context);

        }
        public override void UserEventTriggered(IChannelHandlerContext context, object evt)
        {
            base.UserEventTriggered(context, evt);
        }

        public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
        {
            base.ExceptionCaught(context, exception);
            Log.Logger.Error("SRV Error exception: {0}", exception.StackTrace);
            context.CloseAsync();
            RemoveChannel(context);

        }

        private void RemoveChannel(IChannelHandlerContext context)
        {
           
            IChannelGroup g = clientsGroup;
            if (g == null)
            {
                lock (this)
                {
                    if (clientsGroup == null)
                    {
                        g = clientsGroup = new DefaultChannelGroup(context.Executor);
                    }
                }
            }
            Log.Logger.Error("SRV RemoveChannel 11 {0} ", context.Channel.Id);
           

           
            ICollection<string>  keys = clientIdByIp.Keys;
            Log.Logger.Error("SRV RemoveChannel count {0}", g.Count);
            foreach (string key in keys)
            {
                bool isGetCh = clientIdByIp.TryGetValue(key, out IChannel subCh);
                //Log.Logger.Error("SRV RemoveChannel id:{0} == {1}", context.Channel.Id, subCh.Id);
                if (isGetCh && context.Channel.Id == subCh.Id)
                {
                    Log.Logger.Error("SRV RemoveChannel 33");
                    EventBus.OnLogout(key);
                    _ = clientIdByIp.TryRemove(key, out _);
                }
            }
            
            EventBus.OnSendMsgHandler -= EventBus_OnSendMsgHandler;
        }

        

        public override bool IsSharable => true;
    }
}
